home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / sorgenti vari / wolf3dmacsource.sit / Wolf3DMacSource / EnMove.c < prev    next >
Text File  |  1994-10-04  |  10KB  |  462 lines

  1. /* enmove.c*/
  2. #include "wolfdef.h"
  3.  
  4. dirtype opposite[9] =
  5.     {west,southwest,south,southeast,east,northeast,north,northwest,nodir};
  6.  
  7. dirtype diagonal[9][9] = {
  8. /* east */    {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},
  9.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  10. /* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},
  11.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  12. /* west */    {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},
  13.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  14. /* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},
  15.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  16.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}
  17. };
  18.  
  19. /**********************************
  20.  
  21.     Changes actor to a new state, setting ticcount to the max for that state
  22.  
  23. **********************************/
  24.  
  25. void NewState(actor_t *ActorPtr,stateindex_t state)
  26. {
  27.     state_t *StatePtr;
  28.     StatePtr = &states[state];    /* Get the state record pointer */
  29.     ActorPtr->state = state;        /* Set the actor's state */
  30.     ActorPtr->ticcount = StatePtr->tictime;    /* Set the initial tick value */
  31.     ActorPtr->pic = StatePtr->shapenum;    /* Set the current shape number */
  32. }
  33.  
  34. /**********************************
  35.  
  36.     Attempts to move actor in its current (ActorPtr->dir) direction.
  37.  
  38.     If blocked by either a wall or an actor returns FALSE
  39.  
  40.     If move is either clear or blocked only by a door, returns TRUE and sets
  41.  
  42.     ActorPtr->tilex = new destination
  43.     ActorPtr->tiley
  44.     ActorPtr->areanumber = the floor tile number (0-(MAXAREAS-1)) of destination
  45.     ActorPtr->distance = TILEGLOBAL, or doornumber if a door is blocking the way
  46.  
  47.     If a door is in the way, an OpenDoor call is made to start it opening.
  48.     The actor code should wait until
  49.      doorobjlist[ActorPtr->distance].action = dr_open, meaning the door has been
  50.     fully opened
  51.  
  52. **********************************/
  53.  
  54. /**********************************
  55.  
  56.     Check if I can move in a diagonal direction
  57.     
  58. **********************************/
  59.  
  60. Boolean CheckDiag(Word x,Word y)
  61. {
  62.     /* anything blocking stops diagonal move*/
  63.     if (tilemap[y][x]&(TI_BLOCKMOVE|TI_ACTOR)) {
  64.         return FALSE;        /* It's blocked */
  65.     }
  66.     return TRUE;        /* It's open! */
  67. }
  68.  
  69. /**********************************
  70.  
  71.     Check if I can move in a sideways direction
  72.     also do the code for an actor to open a door
  73.     return 0 if blocked, 1 if open, 2 if I need to open a door
  74.     
  75. **********************************/
  76.  
  77. Word CheckSide(Word x,Word y,actor_t *ActorPtr)
  78. {
  79.     Word temp;
  80.  
  81.     temp=tilemap[y][x];        /* Get the tile */
  82.  
  83.     if (temp & TI_DOOR) {    /* Door? */
  84.         if (!(temp&TI_BLOCKMOVE)) {    /* Not blocked? */
  85.             return 1;    /* door is open*/
  86.         }
  87.         if (ActorPtr->class == CL_DOG)    {
  88.             return 0;    /* dogs can't open doors */
  89.         }
  90.         return 2;        /* I have to open the door */
  91.     }
  92.     if (temp&(TI_BLOCKMOVE|TI_ACTOR)) {    /* Normally blocked? */
  93.         return 0;        /* Can't go this way */
  94.     }
  95.     return 1;        /* I can go! */
  96. }
  97.  
  98. /**********************************
  99.  
  100.     Try to move the actor around
  101.         
  102. **********************************/
  103.  
  104. Boolean TryWalk (actor_t *ActorPtr)
  105. {
  106.     Word x,y;
  107.     Word Temp;
  108.     Word *TileMapPtr;
  109.     Word tile;
  110.  
  111.     x = ActorPtr->goalx;        /* Where is my goal x,y? */
  112.     y = ActorPtr->goaly;
  113.  
  114.     switch (ActorPtr->dir) {    /* Go in my direction */
  115.     case north:                /* Go n,s,e,w */
  116.         --y;
  117.         goto DoSide;
  118.         
  119.     case east:
  120.         ++x;
  121.         goto DoSide;
  122.                 
  123.     case south:
  124.         ++y;
  125.         goto DoSide;
  126.                 
  127.     case west:
  128.         --x;
  129. DoSide:
  130.         Temp = CheckSide(x,y,ActorPtr);    /* See if I can move this way */
  131.         if (!Temp) {        /* Not this way? */
  132.             return FALSE;    /* Exit */
  133.         }
  134.         if (Temp==2) {        /* Door? */
  135.             OpenDoor(&doors[tilemap[y][x]&TI_NUMMASK]);    /* Open the door */
  136.             ActorPtr->flags |= (FL_WAITDOOR|FL_NOTMOVING);    /* Force the actor to pause */
  137.             return TRUE;    /* I'm ok! */
  138.         }
  139.         break;        /* Continue */
  140.         
  141.     case northeast:
  142.         if (!CheckDiag(x+1,y)) {
  143.             return FALSE;
  144.         }
  145.         y--;
  146.         goto FixEast;
  147.  
  148.     case southeast:
  149.         if (!CheckDiag(x+1,y)) {
  150.             return FALSE;
  151.         }
  152.         y++;
  153. FixEast:
  154.         if (!CheckDiag(x,y)) {
  155.             return FALSE;
  156.         }
  157.         x++;
  158.         if (!CheckDiag(x,y)) {
  159.             return FALSE;
  160.         }
  161.         break;
  162.  
  163.     case southwest:
  164.         if (!CheckDiag(x-1,y)) {
  165.             return FALSE;
  166.         }
  167.         y++;
  168.         goto FixWest;
  169.  
  170.     case northwest:
  171.         if (!CheckDiag(x-1,y)) {
  172.             return FALSE;
  173.         }
  174.         y--;
  175. FixWest:
  176.         if (!CheckDiag(x,y)) {
  177.             return FALSE;
  178.         }
  179.         x--;
  180.         if (!CheckDiag(x,y)) {
  181.             return FALSE;
  182.         }
  183.     }
  184.  
  185. /* invalidate the move if moving onto the player */
  186.  
  187.     if (areabyplayer[MapPtr->areasoundnum[ActorPtr->areanumber]]) {
  188.         if (w_abs(((x<<FRACBITS)|0x80) - actors[0].x) < MINACTORDIST
  189.         && w_abs(((y<<FRACBITS)|0x80) - actors[0].y) < MINACTORDIST) {
  190.             return FALSE;
  191.         }
  192.     }
  193.  
  194. /* remove old actor marker*/
  195.  
  196.     tilemap[ActorPtr->goaly][ActorPtr->goalx] &= ~TI_ACTOR;
  197.     
  198. /* place new actor marker*/
  199.  
  200.     TileMapPtr = &tilemap[y][x];    /* Get pointer to cell */
  201.     tile = TileMapPtr[0];            /* Get the cell */
  202.     TileMapPtr[0] = tile | TI_ACTOR;    /* Mark with an actor */
  203.     Temp = ActorPtr - &actors[0];
  204.     MapPtr->tilemap[y][x] = Temp;    /* Save the current actor # */
  205.     ActorPtr->goalx = x;
  206.     ActorPtr->goaly = y;
  207.  
  208.     if (!(tile&TI_DOOR) ) {        /* doorways are not areas*/
  209.         ActorPtr->areanumber = tile&TI_NUMMASK;
  210.     }
  211.     ActorPtr->distance = TILEGLOBAL;    /* Move across 1 whole tile */
  212.     ActorPtr->flags &= ~(FL_WAITDOOR|FL_NOTMOVING);    /* I'm not waiting and I'm moving */
  213.  
  214.     return TRUE;        /* It's ok! */
  215. }
  216.  
  217. /**********************************
  218.     
  219.     Attempts to choose and initiate a movement for actor that sends it towards
  220.     the player while dodging
  221.         
  222. **********************************/
  223.  
  224. void SelectDodgeDir(actor_t *ActorPtr)
  225. {
  226.     int    deltax,deltay;
  227.     Word i;
  228.     Word absdx,absdy;
  229.     dirtype dirtry[5];
  230.     dirtype turnaround,tdir;
  231.  
  232.     turnaround=opposite[ActorPtr->dir];
  233.  
  234.     deltax = actors[0].x - ActorPtr->x;
  235.     deltay = actors[0].y - ActorPtr->y;
  236.  
  237. /* arange 5 direction choices in order of preference*/
  238. /* the four cardinal directions plus the diagonal straight towards*/
  239. /* the player*/
  240.  
  241.     if (deltax>0) {
  242.         dirtry[1]= east;
  243.         dirtry[3]= west;
  244.     } else {
  245.         dirtry[1]= west;
  246.         dirtry[3]= east;
  247.     }
  248.  
  249.     if (deltay>0) {
  250.         dirtry[2]= south;
  251.         dirtry[4]= north;
  252.     } else {
  253.         dirtry[2]= north;
  254.         dirtry[4]= south;
  255.     }
  256.  
  257. /* randomize a bit for dodging*/
  258.  
  259.     absdx = w_abs(deltax);
  260.     absdy = w_abs(deltay);
  261.  
  262.     if (absdx > absdy) {
  263.         tdir = dirtry[1];
  264.         dirtry[1] = dirtry[2];
  265.         dirtry[2] = tdir;
  266.         tdir = dirtry[3];
  267.         dirtry[3] = dirtry[4];
  268.         dirtry[4] = tdir;
  269.     }
  270.  
  271.     if (w_rnd() & 1) {
  272.         tdir = dirtry[1];
  273.         dirtry[1] = dirtry[2];
  274.         dirtry[2] = tdir;
  275.         tdir = dirtry[3];
  276.         dirtry[3] = dirtry[4];
  277.         dirtry[4] = tdir;
  278.     }
  279.  
  280.     dirtry[0] = diagonal[dirtry[1]][dirtry[2]];
  281.  
  282. /* try the directions until one works*/
  283.  
  284.     i = 0;
  285.     do {
  286.         tdir = dirtry[i];
  287.         if (tdir != nodir && tdir != turnaround) {
  288.             ActorPtr->dir = tdir;
  289.             if (TryWalk(ActorPtr)) {    /* Can I go this way? */
  290.                 return;        /* Yep! */
  291.             }
  292.         }
  293.     } while(++i<5);        /* All tries done? */
  294.  
  295. /* turn around only as a last resort*/
  296.  
  297.     if (turnaround != nodir) {
  298.         ActorPtr->dir = turnaround;
  299.         if (TryWalk(ActorPtr)) {
  300.             return;
  301.         }
  302.     }
  303.     ActorPtr->dir = nodir;        /* Stop the motion */
  304.     ActorPtr->flags |= FL_NOTMOVING;    /* Kill the logic! */
  305. }
  306.  
  307. /**********************************
  308.     
  309.     Attempts to choose and initiate a movement for actor that sends it towards
  310.     the player but doesn't try to dodge
  311.         
  312. **********************************/
  313.  
  314. void SelectChaseDir(actor_t *ActorPtr)
  315. {
  316.     int deltax,deltay;
  317.     dirtype d[3];
  318.     dirtype tdir, olddir, turnaround;
  319.  
  320.     olddir = (dirtype) ActorPtr->dir;    /* Save the current direction */
  321.     turnaround=opposite[olddir];    /* What's the opposite direction */
  322.  
  323.     deltax = actors[0].x - ActorPtr->x;    /* Which way to travel? */
  324.     deltay = actors[0].y - ActorPtr->y;
  325.  
  326.     if (deltax>0) {
  327.         d[1]= east;
  328.     } else if (!deltax) {
  329.         d[1]= nodir;
  330.     } else {
  331.         d[1]= west;
  332.     }
  333.     if (deltay>0) {
  334.         d[2]=south;
  335.     } else if (!deltay) {
  336.         d[2]=nodir;
  337.     } else {
  338.         d[2]=north;
  339.     }
  340.     
  341.     if (w_abs(deltay)>w_abs(deltax)) {    /* Swap if Y is greater */
  342.         tdir=d[1];
  343.         d[1]=d[2];
  344.         d[2]=tdir;
  345.     }
  346.  
  347.     if (d[1]==turnaround) {    /* Try not to turn around */
  348.         d[1]=nodir;
  349.     }
  350.     if (d[2]==turnaround) {    /* Try not to turn around */
  351.         d[2]=nodir;
  352.     }
  353.  
  354.     if (d[1]!=nodir) {    /* East/West movement? */
  355.         ActorPtr->dir = d[1];    /* Try to move */
  356.         if (TryWalk(ActorPtr)) {
  357.             return;    /*either moved forward or attacked*/
  358.         }
  359.     }
  360.  
  361.     if (d[2]!=nodir) {    /* North/South movement? */
  362.         ActorPtr->dir =d[2];
  363.         if (TryWalk(ActorPtr)) {
  364.             return;
  365.         }
  366.     }
  367.  
  368. /* there is no direct path to the player, so pick another direction */
  369.  
  370.     if (olddir!=nodir) {
  371.         ActorPtr->dir =olddir;        /* Continue in the old direction */
  372.         if (TryWalk(ActorPtr)) {
  373.             return;
  374.         }
  375.     }
  376.  
  377.     if (w_rnd()&1) {    /*randomly determine direction of search*/
  378.         tdir = north;
  379.         do {
  380.             if (tdir!=turnaround) {
  381.                 ActorPtr->dir =tdir;
  382.                 if (TryWalk(ActorPtr)) {
  383.                     return;
  384.                 }
  385.             }
  386.         } while(++tdir<(west+1));
  387.     } else {
  388.         tdir = west;
  389.         do {
  390.             if (tdir!=turnaround) {
  391.                 ActorPtr->dir =tdir;
  392.                 if ( TryWalk(ActorPtr)) {
  393.                     return;
  394.                 }
  395.             }
  396.         } while(--tdir>=north);
  397.     }
  398.  
  399.     if (turnaround != nodir) {    /* Alright, try backwards now */
  400.         ActorPtr->dir =turnaround;
  401.         if ( TryWalk(ActorPtr) ) {
  402.             return;
  403.         }
  404.     }
  405.     ActorPtr->dir = nodir;        /* Can't move, I give up */
  406.     ActorPtr->flags |= FL_NOTMOVING;
  407. }
  408.  
  409. /**********************************
  410.     
  411.     Moves actor <move> global units in actor->dir direction
  412.     Actors are not allowed to move inside the player
  413.     Does NOT check to see if the move is tile map valid
  414.         
  415. **********************************/
  416.  
  417. void MoveActor(actor_t *ActorPtr,Word move)
  418. {
  419.     Word tryx,tryy;
  420.  
  421.     tryx = ActorPtr->x;    /* Get the x and y */
  422.     tryy = ActorPtr->y;
  423.  
  424.     switch (ActorPtr->dir) {;
  425.     case northeast:        /* Move to the new x,y */
  426.         tryx += move;
  427.     case north:
  428.         tryy -= move;
  429.         break;
  430.         
  431.     case southeast:
  432.         tryy += move;
  433.     case east:
  434.         tryx += move;
  435.         break;
  436.     
  437.     case southwest:
  438.         tryx -= move;
  439.     case south:
  440.         tryy += move;
  441.         break;
  442.         
  443.     case northwest:
  444.         tryy -= move;
  445.     case west:
  446.         tryx -= move;
  447.     }
  448.  
  449. /* check to make sure it's not moving on top of player*/
  450.  
  451.     if (areabyplayer[MapPtr->areasoundnum[ActorPtr->areanumber]]) {
  452.         if (w_abs(tryx - actors[0].x)<MINACTORDIST) {
  453.             if (w_abs(tryy - actors[0].y)<MINACTORDIST) {
  454.                 return;
  455.             }
  456.         }
  457.     }    
  458.     ActorPtr->distance-= move;    /* Remove the distance */
  459.     ActorPtr->x = tryx;        /* Save the new x,y */
  460.     ActorPtr->y = tryy;
  461. }
  462.